import React, {
  useState,
  useRef,
  useContext,
  createContext,
  forwardRef,
  useImperativeHandle,
} from "react";
import { Collapse, Button, Input, Divider, Typography, message } from "antd";

const { Panel } = Collapse;
const { Title, Paragraph, Text } = Typography;

// 1. props（父传子）
function PropsDemo() {
  function Child({ msg }: { msg: string }) {
    return <div>子组件收到: {msg}</div>;
  }
  return <Child msg="父组件通过 props 传递" />;
}

// 2. 回调 props（子传父）
function CallbackPropsDemo() {
  function Child({ onChange }: { onChange: (val: string) => void }) {
    return <Button onClick={() => onChange("子组件数据")}>点击上报</Button>;
  }
  return <Child onChange={(val) => message.info("父收到: " + val)} />;
}

// 3. context（跨层级传递）
const DemoContext = createContext("默认值");
function ContextDemo() {
  return (
    <DemoContext.Provider value="context 传递的数据">
      <Child />
    </DemoContext.Provider>
  );
  function Child() {
    const val = useContext(DemoContext);
    return <div>子组件通过 context 获取: {val}</div>;
  }
}

// 4. ref（父获取子 DOM/方法）
function RefDemo() {
  const inputRef = useRef<HTMLInputElement>(null);
  return (
    <div>
      <input
        ref={inputRef}
        placeholder="ref 获取 input"
        style={{ width: 200, border: "1px solid #ccc", padding: 4 }}
      />
      <Button
        onClick={() => inputRef.current && inputRef.current.focus()}
        style={{ marginLeft: 8 }}
      >
        聚焦
      </Button>
    </div>
  );
}

// 5. forwardRef（子暴露 ref 给父）
const FancyInput = forwardRef<any, {}>((props, ref) => (
  <input
    ref={ref}
    placeholder="forwardRef input"
    style={{ border: "1px solid #ccc", padding: 4 }}
  />
));
function ForwardRefDemo() {
  const ref = useRef<HTMLInputElement>(null);
  return (
    <div>
      <FancyInput ref={ref} />
      <Button
        onClick={() => ref.current && ref.current.focus()}
        style={{ marginLeft: 8 }}
      >
        聚焦
      </Button>
    </div>
  );
}

// 6. useImperativeHandle（自定义暴露方法）
const ImperativeInput = forwardRef<any, {}>((props, ref) => {
  const inputRef = useRef<HTMLInputElement>(null);
  useImperativeHandle(ref, () => ({
    focus: () => inputRef.current && inputRef.current.focus(),
    clear: () => inputRef.current && (inputRef.current.value = ""),
  }));
  return (
    <input
      ref={inputRef}
      placeholder="useImperativeHandle input"
      style={{ border: "1px solid #ccc", padding: 4 }}
    />
  );
});
function ImperativeHandleDemo() {
  const ref = useRef<{ focus: () => void; clear: () => void }>(null);
  return (
    <div>
      <ImperativeInput ref={ref} />
      <Button
        onClick={() => ref.current && ref.current.focus()}
        style={{ marginLeft: 8 }}
      >
        聚焦
      </Button>
      <Button
        onClick={() => ref.current && ref.current.clear()}
        style={{ marginLeft: 8 }}
      >
        清空
      </Button>
    </div>
  );
}

// 7. Redux/MobX/Recoil（全局状态管理）
function GlobalStateDemo() {
  return <div>全局状态管理（如 Redux/MobX/Recoil）需引入相关库，这里略。</div>;
}

// 8. URL params/query（路由参数）
function UrlParamsDemo() {
  return (
    <div>通过 react-router 的 useParams/useSearchParams 获取路由参数。</div>
  );
}

// 9. 事件总线/pubsub
function EventBusDemo() {
  return (
    <div>事件总线（如 mitt、eventemitter3）可实现任意组件间通信，这里略。</div>
  );
}

// 10. localStorage
function LocalStorageDemo() {
  return <div>localStorage/sessionStorage 可实现跨页面数据传递。</div>;
}

// 11. window/global
function GlobalVarDemo() {
  (window as any).myGlobal = "全局变量";
  return <div>window.myGlobal = "全局变量"</div>;
}

const transferList = [
  {
    name: "props（父传子）",
    desc: "最常用的传值方式，父组件通过 props 向子组件传递数据。",
    demo: <PropsDemo />,
  },
  {
    name: "回调 props（子传父）",
    desc: "子组件通过 props 传递的回调函数向父组件上报数据或事件。",
    demo: <CallbackPropsDemo />,
  },
  {
    name: "context（跨层级传递）",
    desc: "通过 React.createContext 实现跨多层组件的数据共享。",
    demo: <ContextDemo />,
  },
  {
    name: "ref（父获取子 DOM/方法）",
    desc: "父组件通过 ref 获取子组件的 DOM 或方法。",
    demo: <RefDemo />,
  },
  {
    name: "forwardRef（子暴露 ref 给父）",
    desc: "子组件通过 forwardRef 暴露 ref 给父组件。",
    demo: <ForwardRefDemo />,
  },
  {
    name: "useImperativeHandle（自定义暴露方法）",
    desc: "配合 forwardRef，子组件自定义暴露给父组件的实例方法。",
    demo: <ImperativeHandleDemo />,
  },
  {
    name: "全局状态管理（Redux/MobX/Recoil）",
    desc: "适合复杂场景，跨组件/全局共享状态。需引入第三方库。",
    demo: <GlobalStateDemo />,
  },
  {
    name: "URL params/query（路由参数）",
    desc: "通过 react-router 的 useParams/useSearchParams 获取路由参数。",
    demo: <UrlParamsDemo />,
  },
  {
    name: "事件总线/pubsub",
    desc: "通过事件总线（如 mitt、eventemitter3）实现任意组件间通信。",
    demo: <EventBusDemo />,
  },
  {
    name: "localStorage/sessionStorage",
    desc: "通过 localStorage/sessionStorage 实现跨页面数据传递。",
    demo: <LocalStorageDemo />,
  },
  {
    name: "window/global（全局变量）",
    desc: "通过 window/global 变量实现全局数据共享（不推荐）。",
    demo: <GlobalVarDemo />,
  },
];

function SafeDemo({ children }: { children: React.ReactNode }) {
  try {
    return <>{children}</>;
  } catch (e: any) {
    return <div style={{ color: "red" }}>案例渲染出错：{e.message}</div>;
  }
}

export default function InteractivePage() {
  return (
    <div style={{ maxWidth: 800, margin: "0 auto", padding: 24 }}>
      <Title level={2}>React 组件传值方式大全</Title>
      <Paragraph>
        <Text strong>
          涵盖父传子、子传父、context、ref、全局状态、路由参数、事件总线等主流传值方式，每种方式都有说明和案例。
        </Text>
      </Paragraph>
      <Divider />
      <Collapse accordion>
        {transferList.map((item) => (
          <Panel header={<Text code>{item.name}</Text>} key={item.name}>
            <Paragraph>
              <Text strong>说明：</Text>
              {item.desc}
            </Paragraph>
            <Paragraph>
              <Text strong>案例：</Text>
            </Paragraph>
            <div style={{ marginBottom: 16 }}>
              <SafeDemo>{item.demo}</SafeDemo>
            </div>
          </Panel>
        ))}
      </Collapse>
    </div>
  );
}
